/**
 *  Copyright (C) 2008-2013  Telosys project org. ( http://www.telosys.org/ )
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *          http://www.gnu.org/licenses/lgpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.telosys.persistence.connection;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

/** 
 * 
 * This class extends the standard "java.sql.Connection" class 
 * ( it encapsulate a standard connection en implements all the 
 * methods of the interface "Connection" )
 *  
 * @author Laurent GUERIN
 *   
 */

/* package */ class SqlConnection implements java.sql.Connection
{
    private java.sql.Connection _conn   = null ;
    
    private ConnectionProviderPool   _pool   = null ; // Pool d'appartenance
    
    private boolean             _bInUse = false ;
  
	//-------------------------------------------------------------  
	/**
	 * Constructor for a standalone connection (without pool)
	 * @param c
	 */
	public SqlConnection( Connection c )
	{
		_conn   = c;
		_pool   = null; // No pool 
		_bInUse = false;
	}
	
	//-------------------------------------------------------------  
	/**
	 * Constructor for a connection managed by a pool
	 * @param c
	 * @param pool 
	 */
	public SqlConnection( Connection c, ConnectionProviderPool pool )
	{
		_conn   = c;
		_pool   = pool; // From pool
		_bInUse = false;
	}

	//-------------------------------------------------------------  
	/**
	 * Fix the "in use" flag to the given value
	 * @param bFlag 
	 */
	protected synchronized void inUse( boolean bFlag )
	{
	    _bInUse = bFlag ;
	}
	
	/**
	 * @return true if the connection is "in use"
	 */
	public synchronized boolean isInUse()
	{
	    return _bInUse;
	}

	//-------------------------------------------------------------  
	/**
	 * Close the real JDBC connection 
	 * @throws SQLException
	 */
	protected void closeJdbcConnection() throws SQLException
	{
		if ( _conn != null )
		{
		    _conn.close();
		}
	}
	
	//-------------------------------------------------------------  
	/**
	 * Tries to close silently the real JDBC connection 
	 */
	protected void tryToCloseJdbcConnection()
	{
		if ( _conn != null )
		{
			try {
			_conn.close();
			}
			catch ( SQLException SqlEx) {}
		}
	}
	
	//-----------------------------------------------------------------------------
	/**
	 * @return true if the connection is considered as "bad" ( not usable )
	 */
	public boolean isBad() 
	{
		boolean badConnection = false;
		try
		{
			if ( _conn.isClosed() ) 
			{
			    return true ; // BAD CONNECTION
			} 
			if ( _conn.getWarnings() != null )
			{
			    return true ; // BAD CONNECTION
			}		        
		}
		catch (Exception e)
		{
			badConnection = true;
			e.printStackTrace();
		}
		return badConnection ;
	}
  
	//-------------------------------------------------------------  
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
	    return _conn.toString() + " ( in use = " + isInUse() + " )" ;
	}


	//-------------------------------------------------------------
    // 
    //-------------------------------------------------------------
    public synchronized void close() throws SQLException
    {
        if (_pool != null) // if the connection belongs to a pool
        {
            _bInUse = false; // Release the connection
        }
        else
        {
            closeJdbcConnection();
        }
    }

    //====================================================================================
    // STANDARD CONNECTION BEHAVIOR ( called by delegation )
    //====================================================================================
    public boolean isClosed() throws SQLException
    {
        return _conn.isClosed();
    }

    //-------------------------------------------------------------
    public boolean isReadOnly() throws SQLException
    {
        return _conn.isReadOnly();
    }

    //-------------------------------------------------------------
    public void setReadOnly(boolean readOnly) throws SQLException
    {
        _conn.setReadOnly(readOnly);
    }

    //-------------------------------------------------------------
    // prepareStatement
    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql) throws SQLException
    {
        return _conn.prepareStatement(sql);
    }

    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
    {
        return _conn.prepareStatement(sql, autoGeneratedKeys);
    }

    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
    {
        return _conn.prepareStatement(sql, columnIndexes);
    }

    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
    {
        return _conn.prepareStatement(sql, columnNames);
    }

    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
    {
        return _conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }

    //-------------------------------------------------------------
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        return _conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    //-------------------------------------------------------------
    // createStatement
    //-------------------------------------------------------------
    public Statement createStatement() throws SQLException
    {
        return _conn.createStatement();
    }

    //-------------------------------------------------------------
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
    {
        return _conn.createStatement(resultSetType, resultSetConcurrency);
    }

    //-------------------------------------------------------------
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        return _conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    //-------------------------------------------------------------
    //  TRANSACTIONS
    //-------------------------------------------------------------
    public boolean getAutoCommit() throws SQLException
    {
        return _conn.getAutoCommit();
    }

    //-------------------------------------------------------------
    public void setAutoCommit(boolean autoCommit) throws SQLException
    {
        _conn.setAutoCommit(autoCommit);
    }

    //-------------------------------------------------------------
    //-------------------------------------------------------------
    public int getTransactionIsolation() throws SQLException
    {
        return _conn.getTransactionIsolation();
    }

    //-------------------------------------------------------------
    public void setTransactionIsolation(int level) throws SQLException
    {
        _conn.setTransactionIsolation(level);
    }

    //-------------------------------------------------------------
    //-------------------------------------------------------------
    public Savepoint setSavepoint() throws SQLException
    {
        return _conn.setSavepoint();
    }

    //-------------------------------------------------------------
    public Savepoint setSavepoint(String name) throws SQLException
    {
        return _conn.setSavepoint(name);
    }

    //-------------------------------------------------------------
    public void releaseSavepoint(Savepoint savepoint) throws SQLException
    {
        _conn.releaseSavepoint(savepoint);
    }

    //-------------------------------------------------------------
    //-------------------------------------------------------------
    public void commit() throws SQLException
    {
        _conn.commit();
    }

    //-------------------------------------------------------------
    public void rollback() throws SQLException
    {
        _conn.rollback();
    }

    //-------------------------------------------------------------
    public void rollback(Savepoint savepoint) throws SQLException
    {
        _conn.rollback(savepoint);
    }

    //-------------------------------------------------------------
    //public void setTypeMap(Map map) throws SQLException
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException // v 1.2.0 ( Java 5 )
    {
        _conn.setTypeMap(map);
    }

    //-------------------------------------------------------------  
    //public Map getTypeMap() throws SQLException
    public Map<String,Class<?>> getTypeMap() throws SQLException // v 1.2.0 ( Java 5 )
    
    {
        return _conn.getTypeMap();
    }

    //-------------------------------------------------------------  
    public void clearWarnings() throws SQLException
    {
        _conn.clearWarnings();
    }

  /* (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
//  public boolean equals(Object obj)
//  {
//      return _conn.equals(obj);
//  }

  
  
  	public String getCatalog() throws SQLException
    {
        return _conn.getCatalog();
    }

    public int getHoldability() throws SQLException
    {
        return _conn.getHoldability();
    }

    public DatabaseMetaData getMetaData() throws SQLException
    {
        return _conn.getMetaData();
    }

    public SQLWarning getWarnings() throws SQLException
    {
        return _conn.getWarnings();
    }
  
  /* (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
//  public int hashCode()
//  {
//      return _conn.hashCode();
//  }

  
  	public String nativeSQL(String sql) throws SQLException
    {
        return _conn.nativeSQL(sql);
    }

    public CallableStatement prepareCall(String sql) throws SQLException
    {
        return _conn.prepareCall(sql);
    }

    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
    {
        return _conn.prepareCall(sql, resultSetType, resultSetConcurrency);
    }

    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        return _conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    public void setCatalog(String catalog) throws SQLException
    {
        _conn.setCatalog(catalog);
    }

	public void setHoldability(int holdability) throws SQLException
	{
	    _conn.setHoldability(holdability);
	}
    
}
